/********************************************************************
//	CharacterList.cpp
//	2013 02 14 - J. A. Cripe jacripe@gmail.com http://wiseeyesent.com
//
//	CharacterList Class Definition File
//	Includes:
//			- Class/Function Definitions
//
********************************************************************/

#include "CharacterList.h"

CharacterList::CharacterList(void) {
	node = NULL;
	idx = -1;
	cnt = 0;
	prior = -1;
}

CharacterList::CharacterList(Character* c) {
	node = c;
	idx = 0;
	cnt = 1;
	prior = 0;
}

CharacterList::CharacterList(CharacterList* l) {
	node = l->node;
	idx = l->idx;
	cnt = l->cnt;
	prior = l->prior;
}

void CharacterList::addChar(Character* c) {
	//List is empty
	if(node == NULL || cnt == 0) {
		node = c;
		prior = idx = 0;
		++cnt;
		return;
	}
	
	//Otherwise, Add Character to End of List
	//First, save current node & index
	Character* tmp = node;
	int tmpI = idx;

	//Iterate to end of list
	while(node->next != NULL && idx < (cnt - 1)) {
		node = node->next;
		++idx;
	}

	//Add Character
	node->next = c;
	c->next = NULL;
	c->prev = node;
		
	//Finally, restore current node & index
	node = tmp;
	idx = tmpI;

	//Always increment count for new node
	++cnt;
}

void CharacterList::insertChar(Character* c, int i) {
	//List is empty
	if(node == NULL || cnt == 0)
		return addChar(c); //Just add new character instead

	//Correct Out of Bounds Errors
	if(i < 0)
		i = 0;
	else if(i >= cnt)
		i = cnt - 1;

	//Save Current Node & Index
	Character* tmp = node;
	int tmpI = idx;

	//Move to requested position
	//Current node is before requested index
	if(idx < i) {
		while(idx != i) {
			node = node->next;
			++idx;
		}
	}
	//Current node is after requested index
	else if(idx > i) {
		while(idx != i) {
			node = node->prev;
			--idx;
		}
	}

	//Insert new node after specified index
	c->prev = node;
	c->next = node->next;
	node->next = c;

	//Incrememnt Count for new Character Added
	++cnt;
}

Character* CharacterList::removeCurrentChar(void) {
	//List is empty
	if(node == NULL || cnt == 0)
		return NULL; //Do Nothing

	Character* retVal = node;

	if(node->prev == NULL) { //First Node
		node = node->next;
		node->prev = NULL;
		idx = 0;
	} else if(node->next == NULL) { //Last Node
		node = node->prev;
		node->next = NULL;
		idx = (cnt - 1) - 1;
	} else { //Middle of List
		node->next->prev = node->prev; //Point Next Node to Previous Node
		node->prev->next = node->next; //Point Previous Node to Next Node
		node = node->prev; //Move to Previous Node
		--idx; //Decrement Index
	}

	//Always Decrement Count for Removed Node
	--cnt;

	return retVal;
}

Character* CharacterList::removeCharAt(int i) {
	//List is Empty
	if(node == NULL || cnt == 0)
		return NULL; //Do Nothing

	Character* retVal = NULL;

	//Save Current Node & Index
	Character* tmp = node;
	int tmpI = idx;

	//Check for Out of Bounds Error
	if(i < 0)
		i = 0;
	else if(i >= cnt)
		i = cnt - 1;

	//If Not At Requested Index, Save Current idx to prior
	if(idx != i) {
		prior = idx;
		//Move to Requested Index & Save to retVal for return
		retVal = this->charAt(i);
	}

	//List is 1 node long
	if(cnt == 1) {
		//NULL all references
		node = node->prev = node->next = NULL;
		//Clear idx & prior values, cnt will be decremented to 0 at end of function
		idx = prior = -1;
	}
	//List is more than 1 node
	else {
		//First Node Requested
		if(i == 0) {
			node = node->next;
			node->prev = NULL;
			idx = 0;
		}
		//Last Node Requested
		else if(i == (cnt - 1)) {
			node = node->prev;
			node->next = NULL;
			idx = (cnt - 1) - 1; //-1 for index starting from 0 & -1 for node removed
		}
		//Interior Node Requested
		else {
			//Remove Node
			node->prev->next = node->next; //Point Previous Node to Next Node
			node->next->prev = node->prev; //Point Next Node to Previous Node
			node = node->prev; //Move to Previous Node
			--idx;
		}
	}

	//Always Decrement Count for Character Removed
	--cnt;

	//Return Node Removed
	return retVal;
}

Character* CharacterList::curr(void) {
	//Return Current Node & NOthing Else
	return node;
}

Character* CharacterList::first(void) {
	//List is Empty
	if(node == NULL || cnt == 0)
		return NULL;

	//Already At First Node
	if(idx == 0)
		return node;

	//Save Current Node & Index
	Character* tmp = node;
	int tmpI = idx;

	//If not at first position
	if(node->prev != NULL || idx != 0) {
		prior = idx; //Save Current Index to Prior

		//Decrement to first position
		while(node->prev != NULL && idx > 0) {
			node = node->prev;
			--idx;
		}
	}

	//Return Node Found
	return node;
}

Character* CharacterList::last(void) {
	//List is empty
	if(node == NULL || cnt == 0)
		return NULL;

	//Already At Last Node
	if(idx == (cnt - 1))
		return node;

	//Save Current Node & Index
	Character* tmp = node;
	int tmpI = idx;

	//Not at Last Node
	if(idx < (cnt - 1)) {
		//Save Current Index to Prior Value
		prior = idx;

		//Increment to Last Node
		while(node->next != NULL && idx < (cnt - 1)) {
			node = node->next;
			++idx;
		}
	}

	//Return node found
	return node;
}

Character* CharacterList::charAt(int i) {
	//List is Empty
	if(node == NULL || cnt == 0)
		return NULL;

	//Correct Out of Bounds
	if(i < 0)
		i = 0;
	else if(i >= cnt)
		i = cnt - 1;

	//Already at requested node
	if(idx == i)
		return node;

	//Save Prior Index Before Moving
	prior = idx;
	
	//Move to requested index
	//Current Index is Before Requested Index
	if(idx < i) {
		while(idx != i) {
			node = node->next;
			++idx;
		}
	}
	//Current Index is After Requested Index
	else if(idx > i) {
		while(idx != i) {
			node = node->prev;
			--idx;
		}
	}

	//Return node found
	return node;
}

Character* CharacterList::next(void) {
	//List is Empty
	if(node == NULL || cnt == 0)
		return NULL; //Return NULL

	//Last Node
	if(node->next == NULL)
		return NULL; //Return NULL, but don't move

	//Move to next node
	prior = idx; //Save Prior Node Index
	node = node->next;
	++idx;

	//Return Node Found
	return node;
}

Character* CharacterList::prev(void) {
	//List is Empty
	if(node == NULL || cnt == 0)
		return NULL; //Return NULL

	//First Node
	if(node->prev == NULL || idx <= 0)
		return NULL; //Return NULL, but don't move

	prior = idx; //Save Prior Node Index
	node = node->prev; //Move to Previous Node
	--idx; //Decrement idx

	//Return Node Found
	return node;
}